package com.ruoyi.project.decision.algorithms;

import com.ruoyi.project.decision.domain.CcfScores;
import com.ruoyi.project.knowledge.domain.OverallScores;

import java.util.*;

public class CcfAlgorithm {
    public List<CcfScores> compute(List<OverallScores> originalScores, float thresholdA, float thresholdB) {
        Map<String, Map<String, Set<String>>> groupedData = new HashMap<>();

        // 按 chainType 和 scenario 分类数据，并创建每个企业的产品列表
        for (OverallScores originalScore : originalScores) {
            String key = originalScore.getChainType() + "-" + originalScore.getScenario();
            groupedData
                    .computeIfAbsent(key, k -> new HashMap<>())
                    .computeIfAbsent(originalScore.getEnterpriseName(), k -> new HashSet<>())
                    .add(originalScore.getProduct());
        }

        List<CcfScores> ccfScoresList = new ArrayList<>();
        List<Float> conflictScores = new ArrayList<>();
        List<Float> cooperationScores = new ArrayList<>();

        // 计算合作/竞争关系
        for (Map.Entry<String, Map<String, Set<String>>> chainScenarioEntry : groupedData.entrySet()) {
            String chainTypeScenario = chainScenarioEntry.getKey();
            String[] parts = chainTypeScenario.split("-");
            String chainType = parts[0];
            String scenario = parts[1];

            Map<String, Set<String>> enterpriseProductMap = chainScenarioEntry.getValue();
            List<String> enterpriseNames = new ArrayList<>(enterpriseProductMap.keySet());

            for (int i = 0; i < enterpriseNames.size(); i++) {
                for (String enterpriseName : enterpriseNames) {
                    String enterpriseNameA = enterpriseNames.get(i);

                    // 如果是同一家企业，跳过判断
                    if (enterpriseNameA.equals(enterpriseName)) {
                        continue;
                    }

                    Set<String> productsA = enterpriseProductMap.get(enterpriseNameA);
                    Set<String> productsB = enterpriseProductMap.get(enterpriseName);

                    // 计算交并比
                    Set<String> intersection = new HashSet<>(productsA);
                    intersection.retainAll(productsB);

                    Set<String> union = new HashSet<>(productsA);
                    union.addAll(productsB);

                    float jaccardIndex = (float) intersection.size() / union.size();
                    String relationshipType;
                    float score;

                    if (jaccardIndex > thresholdA) {
                        relationshipType = "conflict";
                        score = -jaccardIndex;
                        conflictScores.add(score);
                    } else if (jaccardIndex >= thresholdB) {
                        relationshipType = "cooperation";
                        score = jaccardIndex;
                        cooperationScores.add(score);
                    } else {
                        relationshipType = "none";
                        score = 0;
                    }

                    // 创建 CcfScores 对象
                    CcfScores ccfScore = new CcfScores();
                    ccfScore.setChainType(chainType);
                    ccfScore.setScenario(scenario);
                    ccfScore.setEnterpriseNameA(enterpriseNameA);
                    ccfScore.setEnterpriseNameB(enterpriseName);
                    ccfScore.setEvent(originalScores.get(0).getEvent());  // 假设 event 相同
                    ccfScore.setRelationshipType(relationshipType);
                    ccfScore.setScore(score);

                    ccfScoresList.add(ccfScore);
                }
            }
        }

        // 最大-最小归一化
        normalizeScores(ccfScoresList, conflictScores, "conflict");
        normalizeScores(ccfScoresList, cooperationScores, "cooperation");

        return ccfScoresList;
    }

//    private void normalizeScores(List<CcfScores> ccfScoresList, List<Float> scores, String type) {
//        if (scores.isEmpty()) return;
//
//        float minScore = Collections.min(scores);
//        float maxScore = Collections.max(scores);
//
//        for (CcfScores ccfScore : ccfScoresList) {
//            if (ccfScore.getRelationshipType().equals(type)) {
//                float normalizedScore = (ccfScore.getScore() - minScore) / (maxScore - minScore);
//                ccfScore.setScore(normalizedScore);
//            }
//        }
//    }

    private void normalizeScores(List<CcfScores> ccfScoresList, List<Float> scores, String type) {
        if (scores.isEmpty()) return;
        if (scores.isEmpty()) {
            return;
        }

        float minScore = Collections.min(scores);
        float maxScore = Collections.max(scores);

        // 定义正数和负数的归一化范围
        float lowerBoundPositive = 0.1f;
        float upperBoundPositive = 0.99f;
        float lowerBoundNegative = -0.1f;
        float upperBoundNegative = -0.99f;

        if (minScore == maxScore) {
            // 如果最小值和最大值相等，则设置默认归一化分数
            for (CcfScores ccfScore : ccfScoresList) {
                if (ccfScore.getRelationshipType().equals(type)) {
                    float score = ccfScore.getScore();
                    if (score >= 0) {
                        ccfScore.setScore(roundToTwoDecimalPlaces(maxScore));
                    } else {
                        ccfScore.setScore(roundToTwoDecimalPlaces(maxScore));
                    }
                }
            }
        } else {
            for (CcfScores ccfScore : ccfScoresList) {
                if (ccfScore.getRelationshipType().equals(type)) {
                    float score = ccfScore.getScore();
                    float normalizedScore = (score - minScore) / (maxScore - minScore);
                    float scaledScore;
                    if (score >= 0) {
                        // 处理正数分数
                        scaledScore = lowerBoundPositive + (normalizedScore * (upperBoundPositive - lowerBoundPositive));
                    } else {
                        // 处理负数分数
                        scaledScore = lowerBoundNegative + (normalizedScore * (upperBoundNegative - lowerBoundNegative));
                    }
                    ccfScore.setScore(roundToTwoDecimalPlaces(scaledScore));
                }
            }
        }
    }

    private float roundToTwoDecimalPlaces(float value) {
        return Math.round(value * 100.0f) / 100.0f;
    }
}